package top.ltc_cn.minecraft_manager.controller;


import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaCookie;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.stp.StpUtil;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import top.ltc_cn.minecraft_manager.dto.MinecraftLoginRequest;
import top.ltc_cn.minecraft_manager.dto.OidcConfiguration;
import top.ltc_cn.minecraft_manager.entity.main.UserInfo;
import top.ltc_cn.minecraft_manager.entity.minecraft.PlayerInfo;
import top.ltc_cn.minecraft_manager.repository.main.UserInfoRepository;
import top.ltc_cn.minecraft_manager.repository.minecraft.PlayerInfoRepository;
import top.ltc_cn.minecraft_manager.service.PlayerLoginService;
import top.ltc_cn.springboot_tools.common.LtcResult;
import top.ltc_cn.springboot_tools.tools.satoken.stp.StpLoginAuthUtil;

import java.io.IOException;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Optional;

import static top.ltc_cn.minecraft_manager.service.PlayerLoginService.generateSecureState;

@RestController
@RequestMapping("/auth")
@Slf4j
public class PlayerAuthController {

    @Autowired
    private OAuth2ClientProperties oAuth2ClientProperties;
    @Autowired
    private PlayerLoginService playerLoginService;
    @Autowired
    private UserInfoRepository userInfoRepository;
    @Autowired
    private PlayerInfoRepository playerInfoRepository;

    @GetMapping("/login")
    public void login(HttpServletResponse response) throws IOException {
        String state = generateSecureState();

        // 存储 state 到 Cookie（也可以用 Session）
        SaCookie cookie = new SaCookie("oauth2login_state", state);
        cookie.setHttpOnly(true);
        cookie.setSecure(true); // 生产环境建议开启
        cookie.setPath("/");
        SaResponse saResponse = SaHolder.getResponse();
        saResponse.addCookie(cookie);

        // 构造授权 URL
        OAuth2ClientProperties.Registration registration = oAuth2ClientProperties.getRegistration().get("default");
        OAuth2ClientProperties.Provider provider = oAuth2ClientProperties.getProvider().get(registration.getProvider());

        String redirectUri = registration.getRedirectUri();
        String authorizationUrl =
                provider.getIssuerUri() +
                        "?client_id=" + registration.getClientId() +
                        "&response_type=code" +
                        "&scope=openid" +
                        "&redirect_uri=" + redirectUri +
                        "&state=" + state; // 把 state 拼进去

        response.sendRedirect(authorizationUrl);
    }

    @SaCheckLogin
    @GetMapping("/.well-known/openid-configuration/evictCache")
    public void evictOidcConfigCache() {
        try {
            log.debug("清/.well-known/openid-configuration缓存");
            playerLoginService.evictOidcConfigCache();
        } catch (Exception e) {
            // 捕获其他异常（如网络超时等）
            throw new RuntimeException("Cannot EvictOidcConfigCache", e);
        }
    }

    @GetMapping("/callback")
    public LtcResult<?> callback(String code, String state) {
        SaRequest request = SaHolder.getRequest();
        String stateCookie = request.getCookieValue("oauth2login_state");

        // 验证通过，删除 cookie
        SaResponse saResponse = SaHolder.getResponse();
        if (state != null && state.equals(stateCookie)) {
            // 验证通过，删除 cookie
            saResponse.deleteCookie("oauth2login_state");
        } else {
            // 验证失败，重定向到登录页
            return LtcResult.error("Invalid state parameter");
        }

        OAuth2ClientProperties.Registration registration = oAuth2ClientProperties.getRegistration().get("default");
        OAuth2ClientProperties.Provider provider = oAuth2ClientProperties.getProvider().get(registration.getProvider());

        OidcConfiguration oidcConfiguration = playerLoginService.getOidcConfig(provider.getIssuerUri() + "/.well-known/openid-configuration");

        // TODO: 使用 code 获取 access_token
        return playerLoginService.tokenEndpoint(oidcConfiguration, code);
    }

    @GetMapping("/tests")
    @SaCheckLogin
    @Transactional("minecraftTransactionManager")
    public LtcResult<?> tests() {
        long loginId = StpUtil.getLoginIdAsLong();
        try {
            Optional<PlayerInfo> playerInfo = playerInfoRepository.findById(loginId);
            if (playerInfo.isEmpty()) {
                return LtcResult.error("用户不存在");
            }
            log.debug("userInfo: {}", playerInfo);

            return LtcResult.success("获取用户信息成功").setData(playerInfo);
        } catch (Exception e) {
            return LtcResult.error("获取用户信息失败");
        }
    }
}